package korkd.tower;

import java.util.ArrayList;
import java.util.Random;

import org.anddev.andengine.entity.layer.tiled.tmx.TMXLayer;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXTiledMap;

import android.graphics.Point;
import android.util.Log;
import android.util.FloatMath;

public class RoadBuilder 
{	
	// Global ID's for each tile type
	private final static int TL_INNER = 72;
	private final static int TR_INNER = 74;
	private final static int BL_INNER = 104;
	private final static int BR_INNER = 106;
	
	private final static int TL_OUTER = 34;
	private final static int TR_OUTER = 38;
	private final static int BL_OUTER = 98;
	private final static int BR_OUTER = 102;
	
	private final static int ROAD = 68;
	private final static int GRASS = 40;
	private final static int TOP = 36;
	private final static int BOTTOM = 100;
	private final static int LEFT = 66;
	private final static int RIGHT = 70;
	
	private TMXTiledMap mMap;
	private TMXLayer mLayer;
	private Random mRand;
	private int[][] mRoadMap;
	private ArrayList<Point> SideList;
	public Point start;
	public Point end;
	
	RoadBuilder(TMXTiledMap pMap)
	{
		mMap = pMap;
		mLayer = pMap.getTMXLayers().get(0);
		mRand = new Random(System.currentTimeMillis());
		mRoadMap = new int[mMap.getTileColumns()][mMap.getTileRows()]; 
		SideList = new ArrayList<Point>();
	}
	
	
	public void build(Castle c) 
	{
		Point source = new Point();
		Point choice = new Point();
		int xRange, yRange;
		float distance, result;
		boolean build = true;
		
		source.x = (int)(c.getX() + c.getWidth()/2) / mMap.getTileWidth();
		source.y = (int)(c.getY() + c.getHeight()) / mMap.getTileHeight();
	
		result = 10000;
		
		for(Point p : SideList)
		{
			xRange = p.x - source.x;
			yRange = p.y - source.y;
			
			distance = FloatMath.sqrt((xRange * xRange) + (yRange * yRange));
			
			if(distance < result)
			{
				result = distance;
				choice = p;
			}
		}
		
		xRange = choice.x - source.x;
		yRange = choice.y - source.y;
		
		if(yRange == 0)
		{
			yRange = 1;
		}
		
		if(yRange < 0)
		{
			buildVert(source, 1);
			
			if(xRange >= 0)
			{
				buildHorz(source, 3);
			}
			else
			{
				buildHorz(source, -3);
			}
			
			xRange = choice.x - source.x;
			yRange = choice.y - source.y;
		}
		
		for(int i = 1; i < 5; i++)
		{
			if(source.y+i < mMap.getTileRows() && mRoadMap[source.x][source.y+i] == ROAD)
			{
				buildVert(source, i);
				build = false;
				break;
			}
		}
		
		if(build)
		{
			buildVert(source, yRange);
			buildHorz(source, xRange);
		}
	}
	public void buildSideRoad()
	{
		int range;
		
		for(Point p : SideList)
		{
			range = mRand.nextInt(10) + 10;
			
			//Log.i("SideRoad", Integer.toString(p.x)+" "+Integer.toString(p.y));
			buildHorz(p, range);
		}
	}
	
	public void buildMainRoad()
	{
		int range = 0;
		Point p = new Point(mRand.nextInt(20) + 10, 0);
		start = new Point(p);
		mRoadMap[p.x][p.y] = ROAD;
		
		// Generate a main road down the map
		while(p.y < (mMap.getTileRows() - 1))
		{	
			range = mRand.nextInt(5) + 9;
			
			//Log.i("BuildVert", Integer.toString(p.x)+" "+Integer.toString(p.y));
			
			buildVert(p, range);
			
			SideList.add(new Point(p));
			
			range = mRand.nextInt(12) + 8;
			
			if((p.x + range) > mMap.getTileColumns() - 2)
			{
				range = -range;
			}
			
			//Log.i("BuildHorz", Integer.toString(p.x)+" "+Integer.toString(p.y));
			
			if(p.y < mMap.getTileRows() - 1)
			{
				buildHorz(p, range);
				SideList.add(new Point(p));
			}
		}
		end = p;
		Log.i("End Point", Integer.toString(end.x) + " " + Integer.toString(end.y));
		Log.i("Start Point", Integer.toString(start.x) + " " + Integer.toString(start.y));
	}
	
	private void buildVert(Point p, int range) 
	{
		if(range < 0)
		{
			buildUp(p, range);
		}
		else if (range > 0)
		{
			buildDown(p, range);
		}
	}
	
	private void buildHorz(Point p, int range) 
	{
		if(range < 0)
		{
			buildLeft(p, range);
		}
		else if (range > 0)
		{
			buildRight(p, range);
		}
	}
	
	private void buildUp(Point p, int range)
	{
		range = -range;
		for(int i = 0; (i < range) && (p.y != 0); i++)
		{
			p.offset(0, -1);
			
			mRoadMap[p.x][p.y] = ROAD;
		}
	}
	
	private void buildDown(Point p, int range)
	{
		for(int i = 0; (i < range) && (p.y != (mMap.getTileRows() - 1)); i++)
		{
			p.offset(0, 1);
			
			mRoadMap[p.x][p.y] = ROAD;
		}
	}
	
	private void buildLeft(Point p, int range)
	{
		range = -range;
		for(int i = 0; (i < range) && (p.x != 0); i++)
		{
			p.offset(-1, 0);
			
			mRoadMap[p.x][p.y] = ROAD;
		}
	}
	
	private void buildRight(Point p, int range)
	{
		for(int i = 0; (i < range) && (p.x != (mMap.getTileColumns() - 1)); i++)
		{
			p.offset(1, 0);
			
			mRoadMap[p.x][p.y] = ROAD;
		}
	}

	public void draw() 
	{
		for(int j = 0; j < mMap.getTileRows(); j++)
		{
			for(int i = 0; i < mMap.getTileColumns(); i++)
			{
				
				if(mRoadMap[i][j] == ROAD)
				{
					drawTile(ROAD,i,j);
										
					if(j > 0 && i > 0 && j < (mMap.getTileRows()-1) && i < (mMap.getTileColumns()-1))
					{
						if(mRoadMap[i][j-1] == ROAD && mRoadMap[i+1][j] == ROAD)
						{
							drawTile(TR_INNER,i+1,j-1);
							drawTile(LEFT,i-1,j);
							drawTile(BL_OUTER,i-1,j+1);
							drawTile(BOTTOM,i,j+1);
						}
						
						if(mRoadMap[i+1][j] == ROAD && mRoadMap[i][j+1] == ROAD)
						{
							drawTile(BR_INNER,i+1,j+1);
							drawTile(TL_OUTER,i-1,j-1);
							drawTile(LEFT,i-1,j);
							drawTile(TOP,i,j-1);
						}
						
						if(mRoadMap[i][j+1] == ROAD && mRoadMap[i-1][j] == ROAD)
						{
							drawTile(BL_INNER,i-1,j+1);
							drawTile(TR_OUTER,i+1,j-1);
							drawTile(TOP,i,j-1);
							drawTile(RIGHT,i+1,j);
						}
						
						if(mRoadMap[i][j-1] == ROAD && mRoadMap[i-1][j] == ROAD)
						{
							drawTile(TL_INNER,i-1,j-1);
							drawTile(RIGHT,i+1,j);
							drawTile(BR_OUTER,i+1,j+1);
							drawTile(BOTTOM,i,j+1);
						}
					}
					
					if(i > 0 && i < mMap.getTileColumns()-1)
					{
						if(j > 0 && j < mMap.getTileRows()-1)
						{
							drawTile(TL_OUTER, i-1, j-1);
							drawTile(BL_OUTER, i-1, j+1);
							drawTile(TR_OUTER, i+1, j-1);
							drawTile(BR_OUTER, i+1, j+1);
						}
						
						drawTile(LEFT, i-1, j);
						drawTile(RIGHT, i+1, j);
					}
					
					if(j > 0 && j < mMap.getTileRows()-1)
					{
						drawTile(TOP, i, j-1);
						drawTile(BOTTOM, i, j+1);
					}
				}
			}
		}
	}

	private void drawTile(int tile, int i, int j)
	{
		int MapTile = mLayer.getTMXTile(i, j).getGlobalTileID();
		
		if(MapTile == GRASS)
		{
			mLayer.getTMXTile(i, j).setGlobalTileID(mMap, tile);
		}
		else if(MapTile == TR_OUTER || MapTile == BR_OUTER || MapTile == BL_OUTER || MapTile == TL_OUTER)
		{
			mLayer.getTMXTile(i, j).setGlobalTileID(mMap, tile);
		}
		else if(MapTile == TOP || MapTile == LEFT || MapTile == RIGHT || MapTile == BOTTOM)
		{
			if(tile != TR_OUTER && tile != BR_OUTER && tile != BL_OUTER && tile != TL_OUTER)
			{
				mLayer.getTMXTile(i, j).setGlobalTileID(mMap, tile);
			}
		}
		else if(MapTile == TR_INNER || MapTile == BR_INNER || MapTile == BL_INNER || MapTile == TL_INNER)
		{
			if(tile == ROAD)
			{
				mLayer.getTMXTile(i, j).setGlobalTileID(mMap, tile);
			}
		}
	}
}
